package com.dts.server.common.exception;

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.dts.server.common.enums.ResultCode;
import com.dts.server.common.result.HttpResult;

@RestControllerAdvice 
public class GlobalExceptionHandler {
	
	private final static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
	
 	@Autowired
    HttpServletRequest httpServletRequest;
 	 
    /**
     * 异常日志记录
     */
    private void logErrorRequest(Exception e) {
        log.error("报错API URL:{}", httpServletRequest.getRequestURL().toString());
        log.error("异常:{}", e);
    }
    
    /**
     * 参数未通过@Validate验证异常，
     */
    @ExceptionHandler(BindException.class)
    private HttpResult<Object> methodArgumentNotValid(BindException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        if(errors!=null && errors.size()>0){
        	return HttpResult.fail(ResultCode.PARAM_INVALID.getCode(), e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
        }else{
        	return HttpResult.fail(ResultCode.PARAM_INVALID);
        }
    }

    /**
     * 参数未通过@Valid验证异常，
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    private HttpResult<Object> methodArgumentNotValid(MethodArgumentNotValidException exception) {
        return HttpResult.fail(ResultCode.PARAM_INVALID);
    }

    /**
     * 参数格式有误
     */
    @ExceptionHandler({MethodArgumentTypeMismatchException.class, HttpMessageNotReadableException.class})
    private HttpResult<Object> typeMismatch(Exception exception) {
        logErrorRequest(exception);
        return HttpResult.fail(ResultCode.PARAM_MISTYPE);
    }

    /**
     * 缺少参数
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    private HttpResult<Object> missingServletRequestParameter(MissingServletRequestParameterException exception) {
        logErrorRequest(exception);
        return HttpResult.fail(ResultCode.PARAM_MISSING);
    }

    /**
     * 不支持的请求类型
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    private HttpResult<Object> httpRequestMethodNotSupported(HttpRequestMethodNotSupportedException exception) {
        return HttpResult.fail(ResultCode.S_UNSUPPORTED_METHOD);
    }
    
    /**
     * 未知异常
     */
    @ExceptionHandler({NoHandlerFoundException.class})
    private HttpResult<Object> noHandlerFoundExceptionHandler(Exception exception) {
        logErrorRequest(exception);
        return HttpResult.fail(ResultCode.S_URL_NOEXIST);
    }
    
    /**
     * 未知异常
     */
    @ExceptionHandler({HttpClientErrorException.class, IOException.class, Exception.class})
    private HttpResult<Object> commonExceptionHandler(Exception exception) {
        logErrorRequest(exception);
        return HttpResult.fail(ResultCode.S_UNKNOWN_ERROR);
    }

    /**
     * 自定义异常
     */
    @ExceptionHandler(CustomException.class)
    private HttpResult<Object> serviceExceptionHandler(CustomException exception) {
        return HttpResult.fail(exception.getResultCode().getCode(), exception.getMessage());
    }
    
    /**
     * 自定义异常
     */
    @ExceptionHandler(NonResultCodeException.class)
    private HttpResult<Object> serviceExceptionHandler(NonResultCodeException exception) {
    	return HttpResult.fail(exception.getCode(), exception.getMessage());
    }

}
